package usbipserversrv

import (
	log "github.com/sirupsen/logrus"
	"sync"
	"usbipproxy/domain/service"
	"usbipproxy/domain/vo"
)

type UsbipServerSrvMgrServiceImpl struct {
	rwLock    sync.RWMutex
	mgr       map[string]UsbipServerSrvService
	serverCmd service.UsbIpServerCmdService
}

func (u *UsbipServerSrvMgrServiceImpl) Stop() {
	u.rwLock.Lock()
	defer u.rwLock.Unlock()
	for sessId, usbipClient := range u.mgr {
		u.serverCmd.UnBind(usbipClient.GetBusId())
		usbipClient.Stop()
		delete(u.mgr, sessId)
	}
}

func (u *UsbipServerSrvMgrServiceImpl) Remove(busId, sessId string) {

	if busId != "" && sessId == "" {
		u.rwLock.Lock()

		for sid, client := range u.mgr {
			//u.serverCmd.UnBind(client.GetBusId())
			client.Stop()
			log.Infof("UsbipServerSrvMgrServiceImpl Remove:client busId:%v sessId:%v", client.GetBusId(), client.GetSessId())
			delete(u.mgr, sid)
		}
		u.rwLock.Unlock()
		return
	}

	u.rwLock.Lock()
	client := u.mgr[sessId]
	if client != nil {
		//u.serverCmd.UnBind(client.GetBusId())
		client.Stop()
		log.Infof("UsbipServerSrvMgrServiceImpl Remove1:client busId:%v sessId:%v", client.GetBusId(), client.GetSessId())
	}
	delete(u.mgr, sessId)
	u.rwLock.Unlock()
}

func (u *UsbipServerSrvMgrServiceImpl) GetByBusId(busId string) (int64, string, string, bool) {
	u.rwLock.RLock()
	defer u.rwLock.RUnlock()
	for _, usbipClient := range u.mgr {
		if usbipClient.GetBusId() == busId {
			return usbipClient.GetNotifyConnId(), usbipClient.GetVendorId(), usbipClient.GetSessId(), true
		}
	}

	return 0, "", "", false
}

func (u *UsbipServerSrvMgrServiceImpl) DeleteByNotifyConnId(notifyConnId int64) {
	u.rwLock.Lock()
	defer u.rwLock.Unlock()
	for _, client := range u.mgr {
		if client == nil {
			continue
		}
		if client.GetNotifyConnId() == notifyConnId {
			u.serverCmd.UnBind(client.GetBusId())
			client.Stop()
			log.Infof("UsbipServerSrvMgrServiceImpl DeleteByNotifyConnId  Remove:client busId:%v sessId:%v notifyConnId:%v",
				client.GetBusId(), client.GetSessId(), notifyConnId)
			delete(u.mgr, client.GetSessId())
		}
	}

}

func (u *UsbipServerSrvMgrServiceImpl) GetBusIdsByConnId(notifyConnId int64) []*vo.BusInfo {
	var ret []*vo.BusInfo
	u.rwLock.Lock()
	defer u.rwLock.Unlock()
	for _, client := range u.mgr {
		if client == nil {
			continue
		}
		if client.GetNotifyConnId() == notifyConnId {
			ret = append(ret, &vo.BusInfo{
				SessId:   client.GetSessId(),
				BusId:    client.GetBusId(),
				VendorId: client.GetVendorId(),
			})
		}
	}

	return ret
}

func (u *UsbipServerSrvMgrServiceImpl) Add(busId, sessId string, service UsbipServerSrvService) error {
	u.rwLock.Lock()
	defer u.rwLock.Unlock()
	u.mgr[sessId] = service
	log.Infof("UsbipServerSrvMgrServiceImpl add sessId:%v service:%p", sessId, service)
	return nil
}

func (u *UsbipServerSrvMgrServiceImpl) RecvHeartbeatMsg(busId, sessId string) error {
	u.rwLock.RLock()
	defer u.rwLock.RUnlock()
	service := u.mgr[sessId]
	if service != nil {
		log.Debugf("UsbipServerSrvMgrServiceImpl RecvHeartbeatMsg sessId %s", sessId)
		service.RecvHeartbeatMsg()
	} else {
		log.Infof("UsbipServerSrvMgrServiceImpl RecvHeartbeatMsg can not find sessId %s ", sessId)
	}

	return nil
}

func (u *UsbipServerSrvMgrServiceImpl) RecvMsg(busId, sessId string, msg []byte) error {
	u.rwLock.RLock()
	defer u.rwLock.RUnlock()
	service := u.mgr[sessId]
	if service != nil {
		log.Debugf("UsbipServerSrvMgrServiceImpl RecvMsg sessId %s len(msg):%v", sessId, len(msg))
		service.RecvMsg(msg)
	} else {
		log.Infof("UsbipServerSrvMgrServiceImpl RecvMsg can not find sessId %s ", sessId)
	}

	return nil
}

func NewUsbipServerSrvMgrServiceImpl(serverCmd service.UsbIpServerCmdService) UsbipServerSrvMgrService {
	return &UsbipServerSrvMgrServiceImpl{
		serverCmd: serverCmd,
		mgr:       make(map[string]UsbipServerSrvService),
	}
}
